#pragma once

#include <list>
#include "U7FileDefs.h"
#include "TimeQueue.h"

class WorldMap;
class MapChunk;

class BasicObject;
typedef std::list<BasicObject*> OBJLIST;
typedef OBJLIST::iterator OBJITR;
typedef OBJLIST::const_iterator COBJITR;


class IregObject;


class BasicObject
{
	friend class Renderer;

	// no replicated
	BasicObject( const BasicObject& x );
	BasicObject& operator = ( const BasicObject& x );

public:
	IregObject*		container; // not NULL, if this object is contained by 'container'

protected:
	WorldMap*		worldMap;
	MapChunk*		mapChunk;


	SHAPEID			shapeID;
	unsigned char	xt;
	unsigned char	yt;
	unsigned char	zlevel; // 0: ground

	const char*		name;

	int				renderSeq; // for renderer

	OBJLIST			dependencies; // Objects which must be painted before this can be rendered.
	OBJLIST			dependors;    // Objects which must be painted after.

public:
	BasicObject( WorldMap* map, const SHAPEID& shpid );
	virtual ~BasicObject() {}

	void SetMapChunk( MapChunk* mchk );
	MapChunk* GetMapChunk() const;

	const SHAPEID& ShapeID() const;

	const char* Name() const;

	void GetWorldCoords( U7VECTOR3* vec3 ) const;
	void SetWorldCoords( unsigned xt, unsigned yt, unsigned zlevel );
	void GetLocalCoords( U7VECTOR3* vec3 ) const;
	void SetLocalCoords( unsigned char x, unsigned char y, unsigned char z );

	void GetTileSizes( U7VECTOR3* tileSizes ) const;
	void GetAnchorCoords( U7VECTOR2* anchorCoords ) const;
	void GetShapeRect( U7RECT* rc ) const;
	bool Occlude() const;

	void AddDependencies( OBJITR first, OBJITR last );
	void ClearDependencies();

	bool HitTest( int worldX, int worldY, int zlimit ) const;

};

class TerrainObject : public BasicObject
{
public:
	TerrainObject( WorldMap* map, const SHAPEID& shpid ) :
	  BasicObject(map,shpid) {}
};

class AnimatedTerrainObject : public TerrainObject, public ITimeAware
{
	int maxFrames;
	int curFrame;
public:
	AnimatedTerrainObject( WorldMap* map, const SHAPEID& shpid );
	virtual void HandleEvent( unsigned long time, void* context);
};

class IfixObject : public BasicObject
{
public:
	IfixObject( WorldMap* map, const SHAPEID& shpid ) :
	  BasicObject(map, shpid) {}
};

class IregObject : public BasicObject
{
public:
	unsigned char info[19];
	OBJLIST contained;
public:
	IregObject( WorldMap* map, const SHAPEID& shpid, const unsigned char* ireg );
	~IregObject();
	void AddObject( BasicObject* obj );
	bool IsContainer() const;
};

class SpellbookObject : public IregObject
{
public:
	unsigned char circles[9];
public:
	SpellbookObject( WorldMap* map, const SHAPEID& shpid, const unsigned char* data )
		: IregObject( map, shpid, data )
	{
		PIREG_SPELLBOOK_ENTRY e = (PIREG_SPELLBOOK_ENTRY)data;
		circles[0] = e->circle1;
		circles[1] = e->circle2;
		circles[2] = e->circle3;
		circles[3] = e->circle4;
		circles[4] = e->circle5;
		circles[5] = e->circle6;
		circles[6] = e->circle7;
		circles[7] = e->circle8;
		circles[8] = e->circle9;
	}
};




